using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using ICSharpCode.TextEditor.Document;

namespace ICSharpCode.TextEditor.Util
{
	public class RtfWriter
	{
		private static Dictionary<string, int> colors;

		private static int colorNum;

		private static StringBuilder colorString;

		public static string GenerateRtf(TextArea textArea)
		{
			RtfWriter.colors = new Dictionary<string, int>();
			RtfWriter.colorNum = 0;
			RtfWriter.colorString = new StringBuilder();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1031");
			RtfWriter.BuildFontTable(textArea.Document, stringBuilder);
			stringBuilder.Append('\n');
			string value = RtfWriter.BuildFileContent(textArea);
			RtfWriter.BuildColorTable(textArea.Document, stringBuilder);
			stringBuilder.Append('\n');
			stringBuilder.Append("\\viewkind4\\uc1\\pard");
			stringBuilder.Append(value);
			stringBuilder.Append("}");
			return stringBuilder.ToString();
		}

		private static void BuildColorTable(IDocument doc, StringBuilder rtf)
		{
			rtf.Append("{\\colortbl ;");
			rtf.Append(RtfWriter.colorString.ToString());
			rtf.Append("}");
		}

		private static void BuildFontTable(IDocument doc, StringBuilder rtf)
		{
			rtf.Append("{\\fonttbl");
			rtf.Append("{\\f0\\fmodern\\fprq1\\fcharset0 " + doc.TextEditorProperties.Font.Name + ";}");
			rtf.Append("}");
		}

		private static string BuildFileContent(TextArea textArea)
		{
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = true;
			Color color = Color.Black;
			bool flag2 = false;
			bool flag3 = false;
			bool flag4 = false;
			foreach (ISelection item in textArea.SelectionManager.SelectionCollection)
			{
				int num = textArea.Document.PositionToOffset(item.StartPosition);
				int num2 = textArea.Document.PositionToOffset(item.EndPosition);
				for (int i = item.StartPosition.Y; i <= item.EndPosition.Y; i++)
				{
					LineSegment lineSegment = textArea.Document.GetLineSegment(i);
					int num3 = lineSegment.Offset;
					if (lineSegment.Words == null)
					{
						continue;
					}
					foreach (TextWord word in lineSegment.Words)
					{
						switch (word.Type)
						{
						case TextWordType.Space:
							if (item.ContainsOffset(num3))
							{
								stringBuilder.Append(' ');
							}
							num3++;
							break;
						case TextWordType.Tab:
							if (item.ContainsOffset(num3))
							{
								stringBuilder.Append("\\tab");
							}
							num3++;
							flag4 = true;
							break;
						case TextWordType.Word:
						{
							Color color2 = word.Color;
							if (num3 + word.Word.Length > num && num3 < num2)
							{
								string key = color2.R + ", " + color2.G + ", " + color2.B;
								if (!RtfWriter.colors.ContainsKey(key))
								{
									RtfWriter.colors[key] = ++RtfWriter.colorNum;
									RtfWriter.colorString.Append("\\red" + color2.R + "\\green" + color2.G + "\\blue" + color2.B + ";");
								}
								if (color2 != color || flag)
								{
									stringBuilder.Append("\\cf" + RtfWriter.colors[key]);
									color = color2;
									flag4 = true;
								}
								if (flag2 != word.Italic)
								{
									if (word.Italic)
									{
										stringBuilder.Append("\\i");
									}
									else
									{
										stringBuilder.Append("\\i0");
									}
									flag2 = word.Italic;
									flag4 = true;
								}
								if (flag3 != word.Bold)
								{
									if (word.Bold)
									{
										stringBuilder.Append("\\b");
									}
									else
									{
										stringBuilder.Append("\\b0");
									}
									flag3 = word.Bold;
									flag4 = true;
								}
								if (flag)
								{
									stringBuilder.Append("\\f0\\fs" + Math.Round(textArea.TextEditorProperties.Font.Size * 2f));
									flag = false;
								}
								if (flag4)
								{
									stringBuilder.Append(' ');
									flag4 = false;
								}
								string text = ((num3 < num) ? word.Word.Substring(num - num3) : ((num3 + word.Word.Length <= num2) ? word.Word : word.Word.Substring(0, num3 + word.Word.Length - num2)));
								RtfWriter.AppendText(stringBuilder, text);
							}
							num3 += word.Length;
							break;
						}
						}
					}
					if (num3 < num2)
					{
						stringBuilder.Append("\\par");
					}
					stringBuilder.Append('\n');
				}
			}
			return stringBuilder.ToString();
		}

		private static void AppendText(StringBuilder rtfOutput, string text)
		{
			foreach (char c in text)
			{
				switch (c)
				{
				case '\\':
					rtfOutput.Append("\\\\");
					continue;
				case '{':
					rtfOutput.Append("\\{");
					continue;
				case '}':
					rtfOutput.Append("\\}");
					continue;
				}
				if (c < 'Ā')
				{
					rtfOutput.Append(c);
				}
				else
				{
					rtfOutput.Append("\\u" + (short)c + "?");
				}
			}
		}
	}
}
